home *** CD-ROM | disk | FTP | other *** search
- ;void edit_line(return_string,col,row,color,max_len,st,esc,ext,ch_case);
- ; unsigned char *return_string,col,row,color,max_len,st,est,ext,ch_case;
-
- EXTRN _memory_model:byte
- EXTRN _error_code:byte
- EXTRN _beep_on:byte
-
- _TEXT SEGMENT BYTE PUBLIC 'CODE'
- ASSUME CS:_TEXT
- PUBLIC _edit_line
- _edit_line proc near
- push bp ;
- mov bp,sp ;
- push di ;
- push si ;
- cmp _memory_model,0 ;near or far?
- jle begin ;jump if near
- inc bp ;else add 2 to BP
- inc bp ;
- begin: push ds ;
- jmp A5 ;jump over data
- EscapeCode db ? ;holds escape code or zero
- ExtendedCode db ? ;same
- DeleteCase db 0 ;flags that Del or Backspc key hit
- beepon db ? ;keeps _beep_on parameter
- LeftLimit db ? ;left cursor limit on screen
- RightLimit db ? ;right cursor limit
- Case db ? ;flags kind of case change
- CaseChange db ? ;flags whether case change
- Max_Len db ? ;holds MaxLen parameter
- StringEnd db ? ;col of last char of string
- errorcode db ? ;holds return code
- StringPos db ? ;pts to string variable = cursor pos
-
- Beep PROC
- push dx ;save cursor ptr
- cmp cs:beepon,0 ;beep on?
- jz A1 ;jump if not
- mov dl,7 ;beep char
- mov ah,2 ;DOS function to write char
- int 21h ;make the beep
- A1: pop dx ;
- ret
- Beep ENDP
-
- DisplayChars PROC ;writes changed char string on screen
- or di,di ;zero chars to write?
- jz A3 ;
- A2: mov ah,2 ;function to set cursor
- mov bh,0 ;page
- int 10h ;
- mov al,[si] ;get char
- mov bl,[bp+10] ;attribute
- mov bh,0 ;page
- mov cx,1 ;number chars to write
- mov ah,9 ;function number
- int 10h ;
- inc si ;forward string ptr
- inc dl ;forward cursor ptr
- dec di ;loop till all chars shifted
- jnz A2 ;
- cmp cs:DeleteCase,1 ;
- jne A4 ;
- A3: mov cs:DeleteCase,0 ;
- mov byte ptr[si],' ' ;
- inc di ;through loop once more
- jmp short A2 ;go write space at end of string
- A4: ret
- DisplayChars ENDP
-
- A5: mov bl,_beep_on ;get _beep_on value
- mov cs:beepon,bl ;keep in local variable
- cmp _memory_model,2 ;data near or far?
- jb L1 ;
- lds si,dword ptr[bp+4] ;DS:SI pts to Strg
- les di,dword ptr[bp+4] ;ES:DI too
- inc bp ;add 2 to BP since dword ptr
- inc bp ;
- jmp short L2 ;
- L1: mov ax,ds ;ES = DS
- mov es,ax ;
- mov si,[bp+4] ;
- mov di,si ;
- L2: cmp byte ptr[si],0 ;test for null string
- je L4 ;if not null, change to Pascal string
- mov cx,255 ;max string length
- sub al,al ;seek terminating null
- repne scasb ;
- dec di ;point to null
- mov cx,di ;calculate number bytes
- sub cx,si ;
- mov ah,cl ;keep string length
- dec di ;point to last ptr of string
- L3: mov al,es:[di] ;shift the chars
- mov es:[di+1],al ;
- dec di ;
- loop L3 ;
- mov [si],ah ;
- mov di,si ;reset DI
- L4: mov cs:errorcode,0 ;default return code
- mov cs:ExtendedCode,0 ;
- mov cs:EscapeCode,0 ;
- mov al,[bp+18] ;Ext
- mov bl,[bp+16] ;Esc
- cmp al,0 ;escape char is extended code?
- jz A6 ;
- mov cs:EscapeCode,bl ;ASCII code
- jmp short A7 ;
- A6: mov cs:ExtendedCode,bl ;
-
- ;---Figure out character case:
- A7: mov al,[bp+20] ;get CharCase
- mov cs:CaseChange,0 ;flags no case change
- cmp al,97 ;lower case?
- jb A8 ;jump if not
- sub al,32 ;make uppercase
- A8: cmp al,'U' ;specify uppercase?
- jne A9 ;
- mov cs:Case,1 ;uppercase
- inc cs:CaseChange ;1 = case change made
- jmp short A0 ;
- A9: cmp al,'L' ;specify lowercase?
- jne A0 ;
- mov cs:Case,0 ;lowercase
- inc cs:CaseChange ;1 = case change made
-
- ;---Initialize parameters:
- A0: mov dh,[bp+8] ;get Row
- or dh,dh ;zero?
- jz B1 ;quit if so
- dec dh ;count from zero
- mov dl,[bp+6] ;get Col
- or dl,dl ;zero?
- jz B1 ;quit if so
- dec dl ;count from zero
- mov cs:LeftLimit,dl ;set LeftLimit
- mov al,dl ;copy
- mov ah,[bp+12] ;get MaxLen
- mov cs:Max_Len,ah ;copy
- or ah,ah ;zero?
- jnz B2 ;jump ahead if not
- B1: jmp F4 ;quit
- B2: add al,ah ;figure RightLimit
- dec al ;
- mov cs:RightLimit,al ;
- mov al,[si] ;get string length
- cmp al,cs:max_len ;
- jna B3 ;quit if too long
- mov cs:errorcode,1 ;1 = string too long
- jmp short B1 ;quit
- B3: mov bl,al ;copy strg len
- add bl,dl ;add Col offset
- dec bl ;count from zero
- mov cs:StringEnd,bl ;save col pos of end of string
- mov bl,[bp+14] ;get cursor start pos
- inc bl ;adjust to count from 1
- mov cs:StringPos,bl ;save
- or bl,bl ;zero?
- jz B5 ;then assume 1
- cmp bl,al ;start pos in string?
- jna B4 ;jump if so
- mov bl,al ;else set to char after end of string
- inc bl ;
- mov cs:StringPos,bl ;
- B4: dec bl ;count from zero
- add dl,bl ;add to start col
- cmp dl,cs:RightLimit ;cursor in field?
- ja B1 ;out or range error if not
- B5: mov ah,2 ;function to set cursor
- mov bh,0 ;page number
- int 10h ;set the cursor
-
- ;---Ready to go, get keystroke:
- B6: mov di,si ;Ctrl-cursor moves change DI
- mov ah,7 ;DOS function to get keystroke
- int 21h ;
- or al,al ;extended code?
- jz B7 ;
- jmp D6 ;jump ahead if not extended
- B7: mov ah,7 ;get extended code
- int 21h ;
- mov bl,cs:ExtendedCode ;test for escape char
- or bl,bl ;zero = escape not extended code
- jz B8 ;
- cmp bl,al ;the code?
- jne B8 ;
- mov cs:errorcode,2 ;
- jmp F4 ;quit
- B8: cmp al,75 ;cursor-left
- jne C1 ;
- cmp dl,cs:LeftLimit ;cursor against left margin?
- je B0 ;
- dec dl ;dec cursor ptr
- dec cs:StringPos ;dec string ptr
- B9: mov ah,2 ;func to set cursor
- mov bh,0 ;page
- int 10h ;move cursor
- jmp short B6 ;
- B0: call beep ;
- jmp short B6 ;go get next key
- C1: cmp al,77 ;cursor-right
- jne C3 ;
- cmp dl,cs:RightLimit ;cursor against right margin?
- je B0 ;beep if so
- mov al,cs:StringEnd ;don't let go beyond space after last char
- cmp al,255 ;can't move cursor if null string
- je B0 ;
- cmp dl,al ;
- ja B0 ;
- C2: inc dl ;inc cursor ptr
- inc cs:StringPos ;inc string ptr
- jmp short B9 ;go move cursor
- C3: cmp al,115 ;Ctrl cursor-left
- jne C7 ;
- cmp dl,cs:LeftLimit ;cursor against left margin?
- je B0 ;
- sub cx,cx ;
- mov cl,cs:StringPos ;offset of cursor in string
- dec cx ;adjust
- std ;will scan backwards
- add di,cx ;
- mov al,' ' ;seek space char
- cmp byte ptr es:[di],' ' ;at first char of word?
- je C5 ;jump if so
- C4: repne scasb ;
- jnz C6 ;jump if not found
- add cx,2 ;new position
- mov cs:StringPos,cl ;set string ptr
- mov dl,cs:LeftLimit ;
- add dl,cl ;
- dec dl ;
- jmp short B9 ;go set cursor
- C5: mov al,' ' ;
- repe scasb ;seek first non-space char
- jz C6 ;jump if not found
- jmp short C4 ;now find start of next word
- C6: mov cs:StringPos,1 ;
- mov dl,cs:LeftLimit ;
- jmp short B9 ;
- C7: cmp al,116 ;Ctrl cursor-right
- jne D3 ;
- cmp dl,cs:RightLimit ;cursor against left margin?
- je B0 ;
- mov al,cs:StringEnd ;cursor at last char?
- cmp dl,al ;
- jne C8 ;
- C8: inc al ;
- cmp dl,al ;
- jne C9 ;
- jmp B0 ;
- C9: sub cx,cx ;
- mov cl,es:[di] ;get string length
- sub ax,ax ;figure number chars to scan
- mov al,cs:StringPos ;
- sub cl,al ;
- mov bx,cx ;keep copy
- cld ;scan forward
- add di,ax ;set string ptr
- inc di ;
- mov al,' ' ;seek space char
- cmp byte ptr es:[di],' ' ;at space char?
- jne C0 ;
- cmp byte ptr es:[di-1],' ' ;prior char a space?
- je C9B ;if not, run through all spaces
- jmp C2 ;otherwise, just forward cursor 1 col
- C9B: mov al,' ' ;
- repe scasb ;seek first non-space char
- jz D1 ;jump if not found
- C0: repne scasb ;
- jnz D1 ;jump if not found
- sub bx,cx ;number chars traversed
- add dl,bl ;forward cursor ptr
- add cs:StringPos,bl ;forward string ptr
- jmp B9 ;go set cursor
- D1: mov al,[si] ;place cursor at end of string
- cmp al,cs:Max_Len ;
- je D2 ;
- inc al ;
- D2: mov cs:StringPos,al ;
- mov dl,cs:LeftLimit ;figure cursor position
- add dl,al ;
- dec dl ;
- jmp B9 ;
- D3: cmp al,83 ;Del key?
- jne D5 ;
- mov al,[si] ;is there a char above the cursor?
- cmp cs:StringPos,al ;
- jna D4 ;jump if so
- call beep ;beep
- jmp B6 ;go get next key
- D4: jmp E2 ;go join Backspace routine
- D5: jmp B6 ;go get next key
- D6: mov bl,cs:EscapeCode ;test for escape char
- or bl,bl ;zero = escape not extended code
- jz D7 ;
- cmp bl,al ;the code?
- jne D7 ;
- mov cs:errorcode,2 ;
- jmp F4 ;quit
-
- ;---Make case change if required:
- D7: cmp cs:CaseChange,0 ;case change required?
- je D9 ;jump ahead if not
- cmp cs:Case,0 ;all lowercase?
- jne D8 ;jump if not
- cmp al,65 ;see if uppercase
- jb D9 ;
- cmp al,90 ;
- ja D9 ;
- add al,32 ;convert
- jmp short D9 ;
- D8: cmp al,97 ;see if lowercase
- jb D9 ;
- cmp al,122 ;
- ja D9 ;
- sub al,32 ;convert
-
- ;---Intercept CARRIAGE RETURN:
- D9: cmp al,13 ;Carriage Return?
- jne D0 ;jump if not
- jmp F4 ;go quit
-
- ;---Intercept BACKSPACE:
- D0: cmp al,8 ;backspace?
- jne E6 ;jump if not
- cmp dl,cs:LeftLimit ;cursor at start of line?
- jne E1 ;jump if room for backspace
- call beep ;else beep
- jmp short E5 ;
- E1: dec dl ;move cursor ptr to prior char
- dec cs:StringPos ;dec string ptr
-
- ;---For DEL or backspace, remove char from string:
- E2: sub ax,ax ;pt SI to char to be removed
- mov cx,ax ;
- mov cl,[si] ;string length
- mov al,cs:StringPos ;
- sub cx,ax ;number characters to shift
- or cx,cx ;
- jz E4 ;
- add si,ax ;
- E3: mov al,[si+1] ;get next char
- mov [si],al ;shift
- inc si ;next
- loop E3 ;
- mov si,di ;move SI back to descriptor
- E4: dec byte ptr[si] ;dec descriptor
-
- ;---Write the new string:
- mov cs:DeleteCase,1 ;flag that deleting char
- sub ax,ax ;clear AX
- mov al,[si] ;get string length
- sub al,cs:StringPos ;figure length
- inc al ;number chars to display
- sub cx,cx ;
- mov cl,cs:StringPos ;
- add si,cx ;
- push di ;need DI as counter
- mov di,ax ;
- push dx ;save cursor position
- call DisplayChars ;
- dec cs:StringEnd ;
- pop dx ;
- mov ah,2 ;set cursor
- mov bh,0 ;
- int 10h ;
- pop di ;start of string ptr
- mov si,di ;
- E5: jmp B6 ;go get next key
- E6: cmp al,31 ;reject all other control codes
- ja E7 ;
- call beep ;
- jmp B6 ;go get next key
-
- ;---Add a character to the data string:
- E7: mov bl,[si] ;get string length
- cmp bl,cs:Max_len ;in range?
- jne E8 ;jump ahead if OK
- call Beep ;go beep
- jmp B6 ;go get next keystroke
- E8: push ax ;save input char
- sub ax,ax ;point SI to end of string
- mov al,[si] ;
- or ax,ax ;if null, point to first byte
- jnz E9 ;
- inc ax ;
- E9: add si,ax ;
- mov cl,cs:StringEnd ;does cursor follow last char?
- cmp dl,cl ;
- jna E0 ;jump if not
- cmp dl,cs:LeftLimit ;special case when starting will null strg
- jne F2 ;
- E0: sub cl,dl ;number chars
- inc cl ; to shift
- sub ch,ch ;extend to word
- or cx,cx ;test for zero length
- jnz F1 ;jump ahead if nonzero
- dec si ;pull back pointer
- jmp short F2 ;skip character shift
- F1: mov al,[si] ;shift the string segment
- mov [si+1],al ;
- dec si ;
- loop F1 ;
- F2: pop ax ;fetch input char
- inc si ;back to cursor position
- mov [si],al ;insert new char
- mov si,di ;si back to start of string
- inc byte ptr[si] ;inc string descriptor
- inc cs:StringEnd ;forward end-of-strg col ptr
- inc cs:StringPos ;forward string position ptr
- inc dl ;forward cursor ptr
-
- ;---Now rewrite portion of string on display:
- mov cs:DeleteCase,0 ;flag DisplayChars that not Del case
- sub cx,cx ;figure offset in data string
- mov bx,cx ;
- mov cl,[si] ;get string length
- mov bl,cs:StringPos ;
- sub cx,bx ;equals number chars to write - 2
- add cx,2 ;
- add si,bx ;set string ptr
- dec si ;
- push di ;need DI as counter
- mov di,cx ;
- push dx ;save cursor position
- dec dl ;pull back cursor
- call DisplayChars ;go write chars
- pop dx ;restore cursor pos
- cmp dl,cs:RightLimit ;don't push cursor beyond MaxLen
- jna F3 ;
- dec dl ;
- dec cs:StringPos ;
- F3: mov ah,2 ;
- mov bh,0 ;
- int 10h ;
- pop di ;
- mov si,di ;point SI back to string descriptor
- jmp B6 ;go do next keystroke
-
- ;---Exit code:
- F4: mov al,cs:errorcode ;set errorcode
- pop ds ;
- mov _error_code,al ;
- sub cx,cx ;change to C string
- mov cl,[si] ;get string length
- jcxz F6 ;quit if null
- F5: inc si ;
- mov al,[si] ;
- mov [si-1],al ;
- loop F5 ;
- mov byte ptr [si],0 ;null terminator
- F6: pop si ;
- pop di ;
- pop bp ;
- cmp _memory_model,0 ;quit
- jle quit ;
- db 0CBh ;RET far
- quit: ret ;RET near
- _edit_line ENDP
- _TEXT ENDS
- END